
var minX;
var minY;
var maxX;
var maxY;
var origin = [.5,.5];
//var PROJ_CANVAS_HEIGHT = 200;
//var PROJ_CANVAS_WIDTH = 1000;
var rootXML;
var bldgColor = "rgb(230,230,230)";
var layers = ["url","photo","amenities"];
var savedDrawnPoints = [];
var allImages = [];
var bound;

/*
 * this function returns the value of a tag if it has one and returns "" if that tag does not exist
 * 
 */
function getValOfAttribute(attr,node)
{
	for(var i = 0; i <  node.getElementsByTagName("tag").length ; i++)
	{
		var theAttr = node.getElementsByTagName("tag")[i].getAttribute("k");	
		if(theAttr == attr)
			return node.getElementsByTagName("tag")[i].getAttribute("v");
	}
	return "";
}

/**
 * loads an linked image for display on the proj canvas 
 * @param hasImg
 * @param canvas
 * @param pt
 * @param img
 * @param link
 */
function doNewImage(hasImg, canvas, pt,img, link)
{
	img.onload=function()
	{
		
		canvas.strokeStyle = 'red';
		canvas.lineStyle = "rgb(255,0,0)";	 		 		
		canvas.beginPath();
		
		canvas.moveTo(pt[0],pt[1] - 30);
		canvas.lineTo(pt[0],pt[1]);
		canvas.stroke();
		var rect = [pt[0] - (img.width*.1)/2,pt[1] - 30,img.width*.1,img.height*.1];
		canvas.drawImage(	img,rect[0],rect[1],rect[2],rect[3]);	
		if(link != "")
		{
			allImages.push( [    rect,link       ] );
		
		}
	};
	
	img.src=hasImg;	
}

/**
 * this function takes looks at the xml file for meaningful nodes and displays them.
 * @param xml
 * @param bound
 */
function parseNodes()
{
	var loadedImgs = [];	
	for (i = 0; i <= 10; i++)
	{
		loadedImgs[i] = new Image();
	}
	
	var origin = [.5,.5];
  	var theCanvasProj = document.getElementById('canvasProj');
  	canvas_proj_context = theCanvasProj.getContext("2d");
	var offset = 0;
	var count = 0;
	for(var i = 0; i <  rootXML.getElementsByTagName("node").length ; i++)
	{	
		var thisNode = rootXML.getElementsByTagName("node")[i];
		var hasLink = getValOfAttribute("url",thisNode)
		if(hasLink)
		{	
			var pt =  getParaPointOfNode(thisNode);
			var mappedPt =  mapPoint(pt, origin, PROJ_CANVAS_WIDTH, 1, PROJ_CANVAS_HEIGHT);			
					
			drawOnePoint(mappedPt, canvas_proj_context);
			savedDrawnPoints.push( [mappedPt[0],mappedPt[1],hasLink]  );
													
		}
		
		var hasImage = getValOfAttribute("photo",thisNode);
		if(hasImage)
		{
		
			var pt =  getParaPointOfNode(thisNode);
			var mappedPt =  mapPoint(pt, origin, PROJ_CANVAS_WIDTH, 1, PROJ_CANVAS_HEIGHT);
			traceOutput("what "  + hasImage);
			doNewImage(hasImage,canvas_proj_context,mappedPt, loadedImgs[count]);
			count++;	
		}
	} 	
}

/**
 * this function parses the loaded xml file
 * 
 */
var allData = [];

function doXML()
{
	//drawBack();
	//var screenRect = [200,200];  
	if (window.XMLHttpRequest)
	{// code for IE7+, Firefox, Chrome, Opera, Safari
  		xmlhttp=new XMLHttpRequest();
  	}
	else
  	{// code for IE6, IE5
  		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  	}
	xmlhttp.onreadystatechange= function(){
  	
  		if (xmlhttp.readyState==4 && xmlhttp.status==200 )
    	{
  			rootXML = xmlhttp.responseXML;
    		
    		minX = Number(rootXML.getElementsByTagName("bounds")[0].getAttribute("minlon"));
			minY = Number(rootXML.getElementsByTagName("bounds")[0].getAttribute("minlat"));
			maxX = Number(rootXML.getElementsByTagName("bounds")[0].getAttribute("maxlon"));
			maxY = Number(rootXML.getElementsByTagName("bounds")[0].getAttribute("maxlat"));
    		bound = [minX,minY,maxX,maxY];
    	  		 		
	 		parseNodes();	 	
 			for(var i = 0; i < rootXML.getElementsByTagName("way").length  ; i++)
		 	{ 					
 				allData.push( createObjectFromWay( rootXML.getElementsByTagName("way")[i] ) ) ;		 				 		 	
		 	}
 			redraw();  
    	}
  	}
  	
	xmlhttp.open("GET","data/central_square.xml",true);
	xmlhttp.send();
	
}


function redraw()
{
	var canvasOrtho = document.getElementById("canvasOrtho");
	var flatG = canvasOrtho.getContext("2d");
	for(var i = 0; i < allData.length ; i++)
 	{
		/*var thisWay = rootXML.getElementsByTagName("way")[i];
 		var thisKind = thisWay.getElementsByTagName("tag")[0].getAttribute("k");
 		var doFill = false;
 		if(thisKind == "area")
 		{
 			doFill = true;
 		}	*/	 	
 		drawAsBuilding( allData[i], flatG,false);
		
 	}
}

function createObjectFromWay(way)
{
	var points = [];
	for(var j = 0; j < way.getElementsByTagName("nd").length  ; j++)
	{
		var nodeRef = way.getElementsByTagName("nd")[j].getAttribute("ref");//<nd ref="345508696"/>
		
		var theNode = getByID(nodeRef);
		//traceOutput(" huhz " + theNode + "  " + nodeRef  );
	 	points[j] = getParaPointOfNode(theNode);		 			
	}	
	var obj = new Object;
	obj.points = points;
	return obj;
}

function drawBack()
{
	var canvasProj = document.getElementById("canvasProj");
	var ctx = canvasProj.getContext("2d");
	ctx.fillStyle = "rgba(100, 100, 200, 0.5)";  
	traceOutput("AAAAAAAAAAAAA   " + PROJ_CANVAS_WIDTH);
	ctx.fillRect (PROJ_CANVAS_WIDTH*(ANGLE_ORIGIN/360),0,PROJ_CANVAS_WIDTH*(VISION_ANGLE/360),PROJ_CANVAS_HEIGHT); 


}

/**
 * converts the map coordinate to [1,1] parameter
 * @param theNode
 * @param bound
 * @returns
 */
function getParaPointOfNode(theNode)
{
	var paraX = ( Number(theNode.getAttribute("lon")) - bound[0])/(bound[2] - bound[0]);
	var paraY = ( Number(theNode.getAttribute("lat")) - bound[1])/(bound[3] - bound[1]);
	return [paraX,paraY];

}

/**
 * this function draws paths that are closed
 * @param thisWay
 * @param rootXML
 * @param flatG
 * @param bound
 * @param doFill
 */
function drawAsBuilding(wayObj,  flatG, doFill)
{
	
		 		
	drawFlat(wayObj.points, flatG, doFill);
	var canvasProj = document.getElementById("canvasProj");
	var ctx = canvasProj.getContext("2d");

	var pts = calculateProjectionPoints(wayObj.points);	
	if(pts.length > 1)
		drawOnePath(pts, doFill, ctx);	
}

function mapPointOrtho(p)
{
	var x = ORTHO_CANVAS_DIAMETER*p[0];
	var y = ORTHO_CANVAS_DIAMETER*p[1];//(p[1] - bounds[1])/(bounds[3] - bounds[1]);
	return [x,y];

}


function getByID(nodeRef)
{

	for(var i = 0; i < rootXML.getElementsByTagName("node").length  ; i++)
	{
		var thisNodeRef = rootXML.getElementsByTagName("node")[i].getAttribute("id");
				
		if(thisNodeRef == nodeRef)
		{
			//traceOutput("ahhhhh " + rootXML.getElementsByTagName("node")[i])
			return rootXML.getElementsByTagName("node")[i];
		}
		
	}
	return null;
}

/**
 * this function draws the ortho map
 * 
 * @param points
 * @param bound
 * @param g
 * @param doFill
 */
function drawFlat(points, g,doFill)
{
	if(doFill)
	{
		g.fillStyle = "rgb(200,200,200)";
	}
	g.strokeStyle = 'black';
	g.lineStyle = "rgb(200,0,0)";	 		 		
	g.beginPath();
	var point = points[0];
	var x = ORTHO_CANVAS_DIAMETER*point[0];
	var y = ORTHO_CANVAS_DIAMETER -ORTHO_CANVAS_DIAMETER*point[1]	
	g.moveTo(x,y);
	for(var i = 1; i < points.length  ; i++)
	{
		var point = points[i];
		var x = ORTHO_CANVAS_DIAMETER*point[0];
		var y = ORTHO_CANVAS_DIAMETER - ORTHO_CANVAS_DIAMETER*point[1];
		g.lineTo(x,y);
	}
	if(doFill)
	{
		g.fill(); 
	}
	g.stroke();
}



function calculateProjectionPoints(path)
{
	var minUnit = 1;
	var yScale = 1;
	
	var n = 2;
		
	var point = path[0];
	var screenPoints = [];
	var screenPoint = mapPoint(point, origin, PROJ_CANVAS_WIDTH, yScale,PROJ_CANVAS_HEIGHT);
	screenPoints[0] = screenPoint;
	for(i = 1; i < path.length; i++)
	{
		var nextPoint = path[i];
		var nextScreenPoint = mapPoint(nextPoint, origin, PROJ_CANVAS_WIDTH, yScale,PROJ_CANVAS_HEIGHT);
		var d = distance(screenPoint,nextScreenPoint);
		//this checks for curvature, but not for a break!
		var slope =  (nextPoint[1] - point[1] )/ (nextPoint[0] - point[0]);
		var xValAtOrigin =   point[0] + (origin[1] - point[1])/slope ;
		
		// this one checks for crossing the origin
		if( (  ( (xValAtOrigin >= point[0]) && (xValAtOrigin <= nextPoint[0]) ) ||
		 ( (xValAtOrigin <= point[0]) && (xValAtOrigin >= nextPoint[0]) ) ) &&
		 (xValAtOrigin > origin[0])
		 
		 )
		{
			//
			//screenPoints.push( [100,100]);
			return screenPoints;
		}
	
		//this one checks for long paths that need more intermediate points.
		if(d > minUnit)
		{		
			var numToDo = Math.ceil(d/minUnit);
			var paraInc = d/numToDo;
			var vect = [   (nextPoint[0] - point[0])/numToDo, (nextPoint[1] - point[1])/numToDo    ];
			for(var j = 1; j <= numToDo; j++)
			{
				var thisP = [  point[0] + vect[0]*j, point[1] + vect[1]*j  ];
				var mappedP = mapPoint(thisP, origin, PROJ_CANVAS_WIDTH, yScale,PROJ_CANVAS_HEIGHT);
				screenPoints.push(mappedP);
			}
			
			
		}
		
		screenPoints.push(nextScreenPoint);
		screenPoint = nextScreenPoint;
		point = nextPoint;
	}
	return screenPoints;
		
}


function drawOnePoint(pt, drawContext)
{
	//traceOutput("context " + drawContext);

	drawContext.lineStyle = "rgb(200,0,0)";
	drawContext.strokeStyle = 'black';	
	
	drawContext.beginPath();
	
	drawContext.arc(pt[0],pt[1], 3, 0, Math.PI*2, true); 
	drawContext.stroke();	
	
	
}


function drawOnePath(path,doFill, drawContext)
{
				
	drawContext.lineStyle = "rgb(200,0,0)";
	drawContext.strokeStyle = 'black';	
	if(doFill)
	{
		drawContext.fillStyle = bldgColor;
	}	
	var a = path[0];
	drawContext.beginPath();
	drawContext.moveTo(a[0], a[1]);
	for(i = 1; i < path.length; i++)
	{
		var b = path[i];					
		drawContext.lineTo(b[0],b[1]); 		
	}
	drawContext.stroke();	
	if(doFill)
	{
		drawContext.fill(); 
	}

}




function mapPoint(p, origin, width, yScale, h)
{
	var ang = getAng(p[0] - origin[0],p[1] - origin[1]) + Math.PI*(ANGLE_ORIGIN/180);	
	var thisX = width - width*ang/(Math.PI*2);
	var thisY = mapY(origin,p, yScale);//   distance(p,origin)
	return [thisX,PROJ_CANVAS_HEIGHT*thisY ];
	
}





function getDir(a,b)
{
	var d = distance(a,b);
	return [ (b[0] - a[0])/d, (b[1] - a[1])/d ];	
}

function getAng(coordX,coordY)
{
	//return Math.atan2(coordY,coordX);
	var ang ;
	if( coordY < 0) 
	{
		ang = Math.atan2(-coordY,coordX);
		ang = 2*Math.PI - ang;
		//coordX,-coordY
	}
	else
	{
		ang = Math.atan2(coordY,coordX);
	}
	return ang;
}





var personH = .2;
var co = 0;
function mapY(origin,p, yScale)
{
	//tan(ang) = Math.atan (thisY - personH)/(d);
	//angle from  (0,10) to (d,thisY)
	var d = distance(origin,p);
	var thisY = d*d/yScale;
	var theta=Math.atan2(d, thisY - personH);
	//if(co < 50)
	//	traceOutput("huh " + theta);// d + "  " + thisY);
	co++;
	return  theta/Math.PI;// thisY;// theta;// thisY;	
}



function inverseMapY(thisY,yScale)
{
//h - 200*yIWant  = thisY
// (thisY - h)/200

	thisY*=Math.PI
	//do arc-arc tan?
	var oldY = (PROJ_CANVAS_HEIGHT - thisY)/PROJ_CANVAS_HEIGHT;
	if(oldY >= 0)
	{
		return Math.sqrt(oldY)*PROJ_CANVAS_HEIGHT;
	}
	
	return(0);	
}





//var dir = getDir(a,b);
//var norm = [ dir[1], dir[0] ];
/*var angA = getAng(a[0] - origin[0],a[1] - origin[1]);
var angB = getAng(b[0]  - origin[0],b[1] - origin[1]);*/
